(剑指Offer)面试题26:复杂链表的复制

题目:

请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。

在复杂链表中,每个结点除了有一个pNext指针指向下一个结点之外,还有一个pSibling指向链表中的任意结点或者NULL。

结点的定义如下:

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
};

思路:

方法1:

复制原始链表上的每一个结点,并通过pNext连接起来;然后再设置每个结点的pSibling指针。

假设原始链表中某个结点N的pSibling指针指向结点S,那么就需要从头到尾遍历查找结点S,如果从原始链表的头指针开始,经过m步之后达到结点S,那么在复制链表中的结点N'的pSibling指针指向的结点也是距离复制链表s步的结点。通过这种办法就可以为复制链表上的每个结点设置pSibling指针。

时间复杂度:O(N^2)

方法2:

方法1是通过链表查找来得到pSibling指针所指向的结点,实际上我们可以通过空间换取时间,将原始链表和复制链表的结点通过哈希表对应起来,这样查找的时间就从O(N)变为O(1)。具体如下:

复制原始链表上的每个结点N创建N',然后把这些创建出来的结点用pNext连接起来。同时把<N,N'>的配对信息方法一个哈希表中;然后设置复制链表中的每个结点的pSibling指针,如果原始链表中结点N的pSibling指向结点S,那么在复制链表中,对应的N'应该指向S'。

时间复杂度:O(N)

方法3:

在不使用辅助空间的情况下实现O(N)的时间效率。

第一步:根据原始链表的每个结点N创建对应的N',然后将N‘通过pNext接到N的后面;

第二步:设置复制出来的结点的pSibling。假设原始链表上的N的pSibling指向结点S,那么其对应复制出来的N'是N->pNext指向的结点,同样S'也是结点S->pNext指向的结点。

第三步:把长链表拆分成两个链表,把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。

代码:

1、Hash方法:

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
    ComplexListNode():val(0),pNext(NULL),pSibling(NULL){};
};

typedef std::map<ComplexListNode*,ComplexListNode*> MAP;

ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){
    ComplexListNode* pNode=new ComplexListNode();
    ComplexListNode* p=pNode;
    ComplexListNode* tmp;

    while(pHead!=NULL){
        tmp=new ComplexListNode();
        tmp->val=pHead->val;
        p->pNext=tmp;
        hashNode[pHead]=tmp;
        pHead=pHead->pNext;
        p=p->pNext;
    }
    return pNode->pNext;
}

void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){
    while(pCopy!=NULL){
        pCopy->pSibling=hashNode[pHead->pSibling];
        pCopy=pCopy->pNext;
        pHead=pHead->pNext;
    }
}

ComplexListNode* ComplexListCopy(ComplexListNode* pHead){
    ComplexListNode* pCopy;
    MAP hashNode;
    pCopy=CloneNodes(pHead,hashNode);
    SetSiblings(pHead,pCopy,hashNode);
    return pCopy;
}

2、复制连接方法:

#include <iostream>

using namespace std;

struct ComplexListNode{
    int val;
    ComplexListNode* pNext;
    ComplexListNode* pSibling;
    ComplexListNode(int x):val(x),pNext(NULL),pSibling(NULL){};
};

void CloneNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pCloned;
    while(pNode!=NULL){
        pCloned=new ComplexListNode(pNode->val);
        pNode->pNext=pCloned;
        pCloned->pNext=pNode->pNext;
        pNode=pCloned->pNext;
    }
}

void ConnectSiblingNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pCloned;
    while(pNode!=NULL){
        pCloned=pNode->pNext;
        if(pNode->pSibling!=NULL){
            pCloned->pSibling=pNode->pSibling->pNext;
        }
        pNode=pCloned->pNext;
    }
}

ComplexListNode* ReconnectNodes(ComplexListNode* pHead){
    ComplexListNode* pNode=pHead;
    ComplexListNode* pClonedHead=NULL;
    ComplexListNode* pClonedNode=NULL;

    if(pNode!=NULL){
        pClonedHead=pClonedNode=pNode->pNext;
        pNode->pNext=pClonedNode->pNext;
        pNode=pNode->pNext;
    }
    while(pNode!=NULL){
        pClonedNode->pNext=pNode->pNext;
        pClonedNode=pClonedNode->pNext;
        pNode->pNext=pClonedNode->pNext;
        pNode=pNode->pNext;
    }
    return pClonedHead;
}

ComplexListNode* Clone(ComplexListNode* pHead){
    CloneNodes(pHead);
    ConnectSiblingNodes(pHead);
    return ReconnectNodes(pHead);
}

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/f836b2c43afc4b35ad6adc41ec941dba?rp=1

AC代码:

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    typedef std::map<RandomListNode*,RandomListNode*> MAP;
    RandomListNode* CloneNextNode(RandomListNode* pHead,MAP &hashNode){
        RandomListNode* pCopy=new RandomListNode(0);
        RandomListNode* p=pCopy;
        RandomListNode* tmp;
        while(pHead!=NULL){
            tmp=new RandomListNode(pHead->label);
            p->next=tmp;
            hashNode[pHead]=tmp;
            p=p->next;
            pHead=pHead->next;
        }
        return pCopy->next;
    }

    void setRandomNode(RandomListNode* pHead,RandomListNode* pCopy,MAP &hashNode){
        while(pCopy!=NULL){
            pCopy->random=hashNode[pHead->random];
            pCopy=pCopy->next;
            pHead=pHead->next;
        }
    }

    RandomListNode* Clone(RandomListNode* pHead)
    {
        RandomListNode* pCopy;
        MAP hashNode;
        pCopy=CloneNextNode(pHead,hashNode);
        setRandomNode(pHead,pCopy,hashNode);
        return pCopy;
    }
};
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        CloneNodes(pHead);
        CloneRandom(pHead);
        return ReConnectNodes(pHead);
    }
    
    void CloneNodes(RandomListNode* pHead){
        RandomListNode* pCloned;
        while(pHead!=NULL){
            pCloned=new RandomListNode(pHead->label);
            pCloned->next=pHead->next;
            pHead->next=pCloned;
            pHead=pCloned->next;
        }
    }
    
    void CloneRandom(RandomListNode* pHead){
        RandomListNode* pCloned;
        while(pHead!=NULL){
            pCloned=pHead->next;
            if(pHead->random!=NULL){
                pCloned->random=pHead->random->next;
            }
            pHead=pCloned->next;
        }
    }
    
    RandomListNode* ReConnectNodes(RandomListNode* pHead){
        RandomListNode* pClonedHead=NULL;
        RandomListNode* pClonedNode=NULL;
        RandomListNode* pNode=pHead;
        
        if(pNode!=NULL){
            pClonedHead=pClonedNode=pNode->next;
            pNode->next=pClonedNode->next;
            pNode=pNode->next;
        }
        
        while(pNode!=NULL){
            pClonedNode->next=pNode->next;
            pClonedNode=pClonedNode->next;
            pNode->next=pClonedNode->next;
            pNode=pNode->next;
        }
        return pClonedHead;
    }
};

 

posted @ 2015-07-17 15:03  AndyJee  阅读(5507)  评论(0编辑  收藏  举报